home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / misc / coding / midas060 / src / dsm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-16  |  50.9 KB  |  1,760 lines

  1. /*      DSM.C
  2.  *
  3.  * Digital Sound Mixer
  4.  *
  5.  * $Id: dsm.c,v 1.11 1997/01/16 18:41:59 pekangas Exp $
  6.  *
  7.  * Copyright 1996,1997 Housemarque Inc.
  8.  *
  9.  * This file is part of the MIDAS Sound System, and may only be
  10.  * used, modified and distributed under the terms of the MIDAS
  11.  * Sound System license, LICENSE.TXT. By continuing to use,
  12.  * modify or distribute this file you indicate that you have
  13.  * read the license and understand and accept it fully.
  14. */
  15.  
  16. /* Possibly environment dependent code is marked with *!!* */
  17.  
  18. #include "lang.h"
  19. #include "mtypes.h"
  20. #include "errors.h"
  21. #include "mmem.h"
  22. #include "sdevice.h"
  23. #include "dsm.h"
  24. #include "mutils.h"
  25. #include "mglobals.h"
  26.  
  27. #ifndef NOEMS
  28. #include "ems.h"
  29. #endif
  30.  
  31. #ifdef __DPMI__
  32. #include "dpmi.h"
  33. #endif
  34.  
  35. RCSID(const char *dsm_rcsid = "$Id: dsm.c,v 1.11 1997/01/16 18:41:59 pekangas Exp $";)
  36.  
  37.  
  38. #ifndef NULL
  39. #define NULL ((void*) 0L)
  40. #endif
  41.  
  42.  
  43. #define MIXBUFLEN 40                    /* mixing buffer length 1/40th of a
  44.                                            second */
  45.  
  46. unsigned *dsmMixBuffer;                 /* DSM mixing buffer. dsmPlay() writes
  47.                                            the mixed data here. Post-
  48.                                            processing is usually necessary. */
  49. unsigned dsmMixBufferSize;              /* DSM mixing buffer size */
  50.  
  51. /* The following global variables are used internally by different DSM
  52.    functions and should not be accessed by other modules: */
  53.  
  54. unsigned        dsmMixRate;             /* mixing rate in Hz */
  55. unsigned        dsmMode;                /* output mode (see enum
  56.                                            dsmMixMode) */
  57. #ifdef __16__
  58. unsigned        dsmVolTableSeg;         /* volume table segment */
  59. #endif
  60. unsigned        *dsmVolumeTable;        /* pointer to volume table */
  61.  
  62. dsmChannel      *dsmChannels;           /* pointer to channel datas */
  63. dsmSample       *dsmSamples;            /* sample structures */
  64. unsigned        dsmOutputBits;          /* output bit width */
  65.  
  66.  
  67. /* DSM internal variables: */
  68.  
  69. static unsigned *dsmVolTableMem;        /* pointer to volume table returned
  70.                                            by memAlloc(). Used for
  71.                                            deallocating */
  72. static unsigned dsmChOpen;              /* number of open channels */
  73. static volatile unsigned dsmChPlay;     /* 1 if data on channels may be
  74.                                            played */
  75. static unsigned dsmMasterVolume;        /* master volume */
  76.  
  77. static int      dsmMuted;               /* 1 if muted, 0 if not */
  78. static int      dsmPaused;              /* 1 if paused, 0 if not */
  79.  
  80. static unsigned dsmAmplification;       /* amplification level */
  81.  
  82. static void     *mixingRoutines[3][5] = /* Pointers to mixing routines */
  83.     {
  84.         {
  85.             /* Make sure we'll crash right away if mixing mode is 0: */
  86.             NULL, NULL, NULL, NULL, NULL
  87.         },
  88.         {
  89.             /* Mixing routines for all sample types to mono output: */
  90.             &dsmMix8bitMonoMono,
  91.             &dsmMix8bitMonoMono,
  92.             &dsmMix16bitMonoMono,
  93.             &dsmMix8bitStereoMono,
  94.             &dsmMix16bitStereoMono
  95.         },
  96.         {
  97.             /* Mixing routines for all sample types to stereo output: */
  98.             &dsmMix8bitMonoStereo,
  99.             &dsmMix8bitMonoStereo,
  100.             &dsmMix16bitMonoStereo,
  101.             &dsmMix8bitStereoStereo,
  102.             &dsmMix16bitStereoStereo
  103.         }
  104.     };
  105.  
  106.  
  107. /* Calculate log2(sampleSize) based on sample type */
  108. static int dsmSampleShift(int sampleType)
  109. {
  110.     switch ( sampleType )
  111.     {
  112.         case smp8bitStereo:
  113.         case smp16bitMono:
  114.             return 1;
  115.  
  116.         case smp16bitStereo:
  117.             return 2;
  118.     }
  119.     return 0;
  120. }
  121.  
  122.  
  123.  
  124. /****************************************************************************\
  125. *
  126. * Function:     int dsmInit(unsigned mixRate, unsigned mode,
  127. *                   unsigned outputBits);
  128. *
  129. * Description:  Initializes Digital Sound Mixer
  130. *
  131. * Input:        unsigned mixRate        mixing rate in Hz
  132. *               unsigned mode           mixing mode (see enum dsmMixMode)
  133. *               unsigned outputBits     output bit width (if less than
  134. *                                       16, output values are divided
  135. *                                       accordingly - mixing buffer is
  136. *                                       always a sequence of unsigned ints)
  137. *
  138. * Returns:      MIDAS error code
  139. *
  140. \****************************************************************************/
  141.  
  142. int CALLING dsmInit(unsigned mixRate, unsigned mode, unsigned outputBits)
  143. {
  144.     int         error, i;
  145. #if defined(__16__) & defined(__PROTMODE__)
  146.     ulong       baseAddr
  147. #endif
  148.  
  149.     dsmMixRate = mixRate;
  150.     dsmMode = mode;
  151.     dsmOutputBits = outputBits;
  152.  
  153.     dsmChOpen = 0;                      /* no open channels */
  154.     dsmChPlay = 0;                      /* do not play data in channels */
  155.     dsmChannels = NULL;                 /* channel structures not allocated */
  156.     dsmMuted = 0;                       /* not muted */
  157.     dsmPaused = 0;                      /* not paused */
  158.     dsmMasterVolume = 64;               /* master volume maximum */
  159.  
  160.     /* Calculate mixing buffer size: (FIXME) */
  161.     if ( mode == dsmMixStereo )
  162.         dsmMixBufferSize = 2 * sizeof(unsigned) * mixRate / MIXBUFLEN;
  163.     else
  164.         dsmMixBufferSize = sizeof(unsigned) * mixRate / MIXBUFLEN;
  165.  
  166.  
  167. #if 0
  168.     --------------------
  169.     This code is only for the new fast stereo mixing that is not implemented
  170.     yet
  171.     --------------------
  172. #ifdef __16__
  173.     if ( mode == dsmMixStereo )
  174.         dsmMixBufferSize = 4 * mixRate / MIXBUFLEN;
  175.     else
  176.         dsmMixBufferSize = 2 * mixRate / MIXBUFLEN;
  177. #else
  178.     dsmMixBufferSize = sizeof(unsigned) * mixRate / MIXBUFLEN;
  179. #endif
  180. #endif /* #if 0 */
  181.  
  182.     /* Round up mixing buffer size to nearest paragraph: */
  183.     dsmMixBufferSize = (dsmMixBufferSize + 15) & 0xFFFFFFF0;
  184.  
  185.     /* Allocate memory for volume table: (mixing buffer follows
  186.        volume table) */
  187. #ifdef __16__
  188.     if ( (error = memAlloc(VOLLEVELS * 256 * sizeof(unsigned) +
  189.         dsmMixBufferSize+ 16, (void**) &dsmVolTableMem)) != OK )
  190.         PASSERROR(ID_dsmInit);
  191. #else
  192.     if ( (error = memAlloc(VOLLEVELS * 256 * sizeof(unsigned) +
  193.         dsmMixBufferSize + 1024 + 16,
  194.         (void**) &dsmVolTableMem)) != OK )
  195.         PASSERROR(ID_dsmInit);
  196. #endif
  197.     /* (in 16-bit modes the volume table is paragraph aligned and in 32-bit
  198.        modes it has to be aligned to a 1024-byte boundary, hence the
  199.        difference) */
  200.  
  201. #ifdef __16__
  202. #ifdef __REALMODE__
  203.     /* *!!* */
  204.     /* Real mode - align volume table to a beginning of a segment: */
  205.     dsmVolTableSeg = *((unsigned*) ((uchar*)&dsmVolTableMem + 2)) +
  206.         (((*(unsigned*) &dsmVolTableMem) + 15) >> 4);
  207.     /* (now if that isn't ugly code I don't know what is) */
  208. #else
  209.     /* 16-bit protected mode under DPMI - allocate descriptor for volume
  210.        table: */
  211.     if ( (error = dpmiAllocDescriptor(&dsmVolTableSeg)) != OK )
  212.         PASSERROR(ID_dsmInit);
  213.  
  214.     /* Get allocated memory area segment base address to baseAddr: */
  215.     if ( (error = dpmiGetSegmentBase((unsigned)
  216.         (((ulong) dsmVolTableMem) >> 16), &baseAddr)) != OK )
  217.         PASSERROR(ID_dsmInit);
  218.  
  219.     /* Calculate volume table memory start address: */
  220.     baseAddr += ((ulong) dsmVolTableMem) & 0xFFFF;
  221.  
  222.     /* Align volume table to paragraph boundary: */
  223.     baseAddr = (baseAddr + 0x0F) & 0xFFFFFFF0L;
  224.  
  225.     /* Set volume table segment base address: */
  226.     if ( (error = dpmiSetSegmentBase(dsmVolTableSeg, baseAddr)) != OK )
  227.         PASSERROR(ID_dsmInit);
  228.  
  229.     /* Set correct segment limit for volume table area (volume table +
  230.        mixing buffer): */
  231.     if ( (error = dpmiSetSegmentLimit(dsmVolTableSeg, 256*2*VOLLEVELS +
  232.         dsmMixBufferSize)) != OK )
  233.         PASSERROR(ID_dsmInit);
  234. #endif
  235.     /* Point mixing buffer to the memory immediately after the volume
  236.        table: */
  237.     dsmMixBuffer = (unsigned*) ((((ulong) dsmVolTableSeg) << 16) +
  238.         256 * 2 * VOLLEVELS);
  239.  
  240.     /* Build a normal pointer to the volume table: */
  241.     dsmVolumeTable = (unsigned*) (((ulong) dsmVolTableSeg) << 16);
  242. #else
  243.     /* 32-bit mode - align volume table to a 1024-byte boundary: */
  244.     dsmVolumeTable = (unsigned*) ((((unsigned) dsmVolTableMem) + 1023) &
  245.         0xFFFFFC00L);
  246.  
  247.     /* Point mixing buffer to the memory immediately after the volume
  248.        table: */
  249.     dsmMixBuffer = (unsigned*) (((unsigned)dsmVolumeTable) +
  250.         256 * VOLLEVELS * sizeof(unsigned));
  251. #endif
  252.  
  253.     /* Allocate memory for sample structures: */
  254.     if ( (error = memAlloc(MAXSAMPLES * sizeof(dsmSample), (void**)
  255.         &dsmSamples)) != OK )
  256.         PASSERROR(ID_dsmInit);
  257.  
  258.     /* Mark all samples unused: */
  259.     for ( i = 0; i < MAXSAMPLES; i++ )
  260.         dsmSamples[i].inUse = 0;
  261.  
  262.     return OK;
  263. }
  264.  
  265.  
  266.  
  267.  
  268. /****************************************************************************\
  269. *
  270. * Function:     int dsmClose(void)
  271. *
  272. * Description:  Uninitializes Digital Sound Mixer
  273. *
  274. * Returns:      MIDAS error code
  275. *
  276. \****************************************************************************/
  277.  
  278. int CALLING dsmClose(void)
  279. {
  280.     int         error;
  281.  
  282. #if defined(__16__) & defined(__PROTMODE__)
  283.     /* Deallocate volume table segment descriptor: */
  284.     if ( (error = dpmiFreeDescriptor(dsmVolTableSeg)) != OK )
  285.         PASSERROR(ID_dsmClose);
  286. #endif
  287.  
  288.     /* Deallocate volume table and mixing buffer: */
  289.     if ( (error = memFree(dsmVolTableMem)) != OK )
  290.         PASSERROR(ID_dsmClose);
  291.  
  292.     /* Deallocate sample structures: */
  293.     if ( (error = memFree(dsmSamples)) != OK )
  294.         PASSERROR(ID_dsmClose);
  295.  
  296.     return OK;
  297. }
  298.  
  299.  
  300.  
  301.  
  302. /****************************************************************************\
  303. *
  304. * Function:     int dsmGetMixRate(unsigned *mixRate)
  305. *
  306. * Description:  Reads the actual mixing rate
  307. *
  308. * Input:        unsigned *mixRate       pointer to mixing rate variable
  309. *
  310. * Returns:      MIDAS error code.
  311. *               Mixing rate, in Hz, is stored in *mixRate
  312. *
  313. \****************************************************************************/
  314.  
  315. int CALLING dsmGetMixRate(unsigned *mixRate)
  316. {
  317.     *mixRate = dsmMixRate;
  318.     return OK;
  319. }
  320.  
  321.  
  322.  
  323.  
  324. /****************************************************************************\
  325. *
  326. * Function:     int dsmOpenChannels(unsigned channels)
  327. *
  328. * Description:  Opens channels for output
  329. *
  330. * Input:        unsigned channels       number of channels to open
  331. *
  332. * Returns:      MIDAS error code
  333. *
  334. \****************************************************************************/
  335.  
  336. int CALLING dsmOpenChannels(unsigned channels)
  337. {
  338.     int         error;
  339.  
  340.     dsmChPlay = 0;                      /* data on channels may not be
  341.                                            played */
  342.     dsmChOpen = channels;
  343.     dsmMuted = 0;                       /* not muted */
  344.     dsmPaused = 0;                      /* not paused */
  345.  
  346.     /* Allocate memory for channel structures: */
  347.     if ( (error = memAlloc(channels * sizeof(dsmChannel), (void**)
  348.         &dsmChannels)) != OK )
  349.         PASSERROR(ID_dsmOpenChannels);
  350.  
  351.     /* Set default amplification level and calculate volume table: */
  352.     if ( (error = dsmSetAmplification(64)) != OK )
  353.         PASSERROR(ID_dsmOpenChannels);
  354.  
  355.     /* Clear all channels: */
  356.     if ( (error = dsmClearChannels()) != OK )
  357.         PASSERROR(ID_dsmOpenChannels);
  358.  
  359.     dsmChPlay = 1;                      /* data on channels may now be
  360.                                            played */
  361.     return OK;
  362. }
  363.  
  364.  
  365.  
  366.  
  367. /****************************************************************************\
  368. *
  369. * Function:     int dsmCalcVolTable(unsigned amplification)
  370. *
  371. * Description:  Calculates a new volume table
  372. *
  373. * Input:        unsigned amplification  Amplification level. 64 - normal
  374. *                                       (100%), 32 = 50%, 128 = 200% etc.
  375. *
  376. * Returns:      MIDAS error code
  377. *
  378. \****************************************************************************/
  379.  
  380. int CALLING dsmCalcVolTable(unsigned amplification)
  381. {
  382.     int         volume, value;
  383.     long        temp;
  384.     unsigned    *tablePtr;              /* current volume table position */
  385.  
  386.     /* FIXME - does not support new fast stereo mixing */
  387.  
  388.     tablePtr = dsmVolumeTable;
  389.  
  390.     for ( volume = 0; volume < VOLLEVELS; volume++ )
  391.     {
  392.         for ( value = -128; value < 128; value++ )
  393.         {
  394.             /*!!*/
  395.             temp = ((long) (value * volume)) * ((long) amplification) / 64L;
  396.             temp = (temp * 256L / ((long)(VOLLEVELS-1)) / ((long) dsmChOpen))
  397.                 >> (16 - dsmOutputBits);
  398.             *(tablePtr++) = (unsigned) (temp);
  399.         }
  400.     }
  401.  
  402.     return OK;
  403. }
  404.  
  405.  
  406.  
  407.  
  408. /****************************************************************************\
  409. *
  410. * Function:     int dsmCloseChannels(void)
  411. *
  412. * Description:  Closes open output channels
  413. *
  414. * Returns:      MIDAS error code
  415. *
  416. \****************************************************************************/
  417.  
  418. int CALLING dsmCloseChannels(void)
  419. {
  420.     int         error;
  421.  
  422.     /* Check that channels have been opened: */
  423.     if ( dsmChOpen == 0 )
  424.     {
  425.         /* No open channels - return error: */
  426.         ERROR(errNoChannels, ID_dsmCloseChannels);
  427.         return errNoChannels;
  428.     }
  429.  
  430.     dsmChPlay = 0;                      /* do not play data on channels */
  431.  
  432.     /* Deallocate channel structures: */
  433.     if ( (error = memFree(dsmChannels)) != OK )
  434.         PASSERROR(ID_dsmCloseChannels)
  435.  
  436.     dsmChOpen = 0;                      /* no open channels */
  437.  
  438.     return OK;
  439. }
  440.  
  441.  
  442.  
  443.  
  444. /****************************************************************************\
  445. *
  446. * Function:     int dsmClearChannels(void)
  447. *
  448. * Description:  Clears open channels (removes all sounds)
  449. *
  450. * Returns:      MIDAS error code
  451. *
  452. \****************************************************************************/
  453.  
  454. int CALLING dsmClearChannels(void)
  455. {
  456.     unsigned    i;
  457.     dsmChannel  *chan;
  458.  
  459.     /* Check that channels have been opened: */
  460.     if ( dsmChOpen == 0 )
  461.     {
  462.         /* No open channels - return error: */
  463.         ERROR(errNoChannels, ID_dsmCloseChannels);
  464.         return errNoChannels;
  465.     }
  466.  
  467.     /* Remove sounds from channels: */
  468.     for ( i = 0; i < dsmChOpen; i++ )
  469.     {
  470.         chan = &dsmChannels[i];
  471.         chan->status = dsmChanStopped;  /* playing is stopped */
  472.         chan->sampleHandle = 0;         /* no sample selected */
  473.         chan->sampleChanged = 0;        /* sample not changed */
  474.         chan->sampleType = smpNone;     /* no sample */
  475.         chan->samplePos = sdSmpNone;    /* no sample */
  476.         chan->rate = 0;                 /* no playing rate set */
  477.         chan->direction = 1;            /* forward direction */
  478.         chan->panning = panMiddle;      /* channel at middle */
  479.         chan->muted = 0;                /* channel not muted */
  480.         chan->LoopCallback = NULL;      /* no loop callback */
  481.     }
  482.  
  483.     return OK;
  484. }
  485.  
  486.  
  487.  
  488.  
  489. /****************************************************************************\
  490. *
  491. * Function:     int dsmMute(int mute)
  492. *
  493. * Description:  Mutes all channels
  494. *
  495. * Input:        int mute                1 = mute, 0 = un-mute
  496. *
  497. * Returns:      MIDAS error code
  498. *
  499. \****************************************************************************/
  500.  
  501. int CALLING dsmMute(int mute)
  502. {
  503.     dsmMuted = mute;
  504.     return OK;
  505. }
  506.  
  507.  
  508.  
  509.  
  510. /****************************************************************************\
  511. *
  512. * Function:     int dsmPause(int pause)
  513. *
  514. * Description:  Pauses or resumes playing
  515. *
  516. * Input:        int pause               1 = pause, 0 = resume
  517. *
  518. * Returns:      MIDAS error code
  519. *
  520. \****************************************************************************/
  521.  
  522. int CALLING dsmPause(int pause)
  523. {
  524.     dsmPaused = pause;
  525.     return OK;
  526. }
  527.  
  528.  
  529.  
  530.  
  531. /****************************************************************************\
  532. *
  533. * Function:     int dsmSetMasterVolume(unsigned masterVolume)
  534. *
  535. * Description:  Sets the master volume
  536. *
  537. * Input:        unsigned masterVolume   master volume (0 - 64)
  538. *
  539. * Returns:      MIDAS error code
  540. *
  541. \****************************************************************************/
  542.  
  543. int CALLING dsmSetMasterVolume(unsigned masterVolume)
  544. {
  545.     dsmMasterVolume = masterVolume;
  546.     return OK;
  547. }
  548.  
  549.  
  550.  
  551.  
  552. /****************************************************************************\
  553. *
  554. * Function:     int dsmGetMasterVolume(unsigned *masterVolume)
  555. *
  556. * Description:  Reads the master volume
  557. *
  558. * Input:        unsigned *masterVolume  pointer to master volume
  559. *
  560. * Returns:      MIDAS error code. Master volume is written to *masterVolume.
  561. *
  562. \****************************************************************************/
  563.  
  564. int CALLING dsmGetMasterVolume(unsigned *masterVolume)
  565. {
  566.     *masterVolume = dsmMasterVolume;
  567.     return OK;
  568. }
  569.  
  570.  
  571.  
  572.  
  573. /****************************************************************************\
  574. *
  575. * Function:     int dsmSetAmplification(unsigned amplification)
  576. *
  577. * Description:  Sets amplification level and calculates new volume table.
  578. *
  579. * Input:        unsigned amplification  amplification level, 64 = normal
  580. *
  581. * Returns:      MIDAS error code
  582. *
  583. \****************************************************************************/
  584.  
  585. int CALLING dsmSetAmplification(unsigned amplification)
  586. {
  587.     int         error;
  588.  
  589.     dsmAmplification = amplification;
  590.  
  591.     if ( (error = dsmCalcVolTable(amplification)) != OK )
  592.         PASSERROR(ID_dsmSetAmplification)
  593.  
  594.     return OK;
  595. }
  596.  
  597.  
  598.  
  599.  
  600. /****************************************************************************\
  601. *
  602. * Function:     int dsmGetAmplification(unsigned *amplification)
  603. *
  604. * Description:  Reads the amplification level
  605. *
  606. * Input:        unsigned *amplification   pointer to amplification level
  607. *
  608. * Returns:      MIDAS error code. Amplification level is written to
  609. *               *amplification.
  610. *
  611. \****************************************************************************/
  612.  
  613. int CALLING dsmGetAmplification(unsigned *amplification)
  614. {
  615.     *amplification = dsmAmplification;
  616.     return OK;
  617. }
  618.  
  619.  
  620.  
  621.  
  622. /****************************************************************************\
  623. *
  624. * Function:     int dsmPlaySound(unsigned channel, ulong rate)
  625. *
  626. * Description:  Starts playing a sound
  627. *
  628. * Input:        unsigned channel        channel number
  629. *               ulong rate              playing rate in Hz
  630. *
  631. * Returns:      MIDAS error code
  632. *
  633. \****************************************************************************/
  634.  
  635. int CALLING dsmPlaySound(unsigned channel, ulong rate)
  636. {
  637.     int         error;
  638.  
  639.     /* Check that the channel number is legal and channels are open: */
  640.     if ( channel >= dsmChOpen )
  641.     {
  642.         ERROR(errInvalidChanNumber, ID_dsmPlaySound);
  643.         return errInvalidChanNumber;
  644.     }
  645.  
  646.     /* Playing sound: */
  647.     dsmChannels[channel].status = dsmChanPlaying;
  648.  
  649.     /* Set playing rate: */
  650.     if ( (error = dsmSetRate(channel, rate)) != OK )
  651.         PASSERROR(ID_dsmPlaySound)
  652.  
  653.     /* Set playing position to the beginning of the sample: */
  654.     if ( (error = dsmSetPosition(channel, 0)) != OK )
  655.         PASSERROR(ID_dsmPlaySound)
  656.  
  657.     return OK;
  658. }
  659.  
  660.  
  661.  
  662.  
  663. /****************************************************************************\
  664. *
  665. * Function:     int dsmReleaseSound(unsigned channel)
  666. *
  667. * Description:  Releases the current sound from the channel. If sdLoop1Rel or
  668. *               sdLoop2 looping modes are used, playing will be continued from
  669. *               the release part of the current sample (data after the end
  670. *               of the first loop) after the end of the first loop is reached
  671. *               next time, otherwise the sound will be stopped.
  672. *
  673. * Input:        unsigned channel        channel number
  674. *
  675. * Returns:      MIDAS error code
  676. *
  677. \****************************************************************************/
  678.  
  679. int CALLING dsmReleaseSound(unsigned channel)
  680. {
  681.     dsmChannel  *chan;
  682.  
  683.     /* Check that the channel number is legal and channels are open: */
  684.     if ( channel >= dsmChOpen )
  685.     {
  686.         ERROR(errInvalidChanNumber, ID_dsmReleaseSound);
  687.         return errInvalidChanNumber;
  688.     }
  689.  
  690.     chan = &dsmChannels[channel];
  691.  
  692.     /* If no sound is being played in the channel do nothing: */
  693.     if ( chan->status == dsmChanPlaying )
  694.     {
  695.         if ( (chan->loopMode == sdLoop1Rel) || (chan->loopMode == sdLoop2) )
  696.         {
  697.             /* Release sound - continue from release portion of the sample: */
  698.             chan->status = dsmChanReleased;
  699.         }
  700.         else
  701.         {
  702.             /* One loop only or no looping - let playback continue normally */
  703.         }
  704.     }
  705.  
  706.     return OK;
  707. }
  708.  
  709.  
  710.  
  711.  
  712. /****************************************************************************\
  713. *
  714. * Function:     int dsmStopSound(unsigned channel)
  715. *
  716. * Description:  Stops playing a sound
  717. *
  718. * Input:        unsigned channel        channel number
  719. *
  720. * Returns:      MIDAS error code
  721. *
  722. \****************************************************************************/
  723.  
  724. int CALLING dsmStopSound(unsigned channel)
  725. {
  726.     /* Check that the channel number is legal and channels are open: */
  727.     if ( channel >= dsmChOpen )
  728.     {
  729.         ERROR(errInvalidChanNumber, ID_dsmStopSound);
  730.         return errInvalidChanNumber;
  731.     }
  732.  
  733.     /* Stop sound: */
  734.     dsmChannels[channel].status = dsmChanStopped;
  735.  
  736.     return OK;
  737. }
  738.  
  739.  
  740.  
  741.  
  742. /****************************************************************************\
  743. *
  744. * Function:     int dsmSetRate(unsigned channel, ulong rate)
  745. *
  746. * Description:  Sets the playing rate
  747. *
  748. * Input:        unsigned channel        channel number
  749. *               ulong rate              playing rate in Hz
  750. *
  751. * Returns:      MIDAS error code
  752. *
  753. \****************************************************************************/
  754.  
  755. int CALLING dsmSetRate(unsigned channel, ulong rate)
  756. {
  757.     /* Check that the channel number is legal and channels are open: */
  758.     if ( channel >= dsmChOpen )
  759.     {
  760.         ERROR(errInvalidChanNumber, ID_dsmSetRate);
  761.         return errInvalidChanNumber;
  762.     }
  763.  
  764.     /* Set the playing rate: */
  765.     dsmChannels[channel].rate = rate;
  766.  
  767.     return OK;
  768. }
  769.  
  770.  
  771.  
  772.  
  773. /****************************************************************************\
  774. *
  775. * Function:     int dsmGetRate(unsigned channel, ulong *rate)
  776. *
  777. * Description:  Reads the playing rate on a channel
  778. *
  779. * Input:        unsigned channel        channel number
  780. *               ulong *rate             pointer to playing rate
  781. *
  782. * Returns:      MIDAS error code. Playing rate is written to *rate, 0 if
  783. *               no sound is being played.
  784. *
  785. \****************************************************************************/
  786.  
  787. int CALLING dsmGetRate(unsigned channel, ulong *rate)
  788. {
  789.     /* Check that the channel number is legal and channels are open: */
  790.     if ( channel >= dsmChOpen )
  791.     {
  792.         ERROR(errInvalidChanNumber, ID_dsmGetRate);
  793.         return errInvalidChanNumber;
  794.     }
  795.  
  796.     if ( (dsmChannels[channel].status == dsmChanStopped) ||
  797.         (dsmChannels[channel].status == dsmChanEnd) )
  798.     {
  799.         /* Nothing is being played - write 0 to *rate: */
  800.         *rate = 0;
  801.     }
  802.     else
  803.     {
  804.         /* Write the playing rate: */
  805.         *rate = dsmChannels[channel].rate;
  806.     }
  807.  
  808.     return OK;
  809. }
  810.  
  811.  
  812.  
  813.  
  814. /****************************************************************************\
  815. *
  816. * Function:     int dsmSetVolume(unsigned channel, unsigned volume)
  817. *
  818. * Description:  Sets the playing volume
  819. *
  820. * Input:        unsigned channel        channel number
  821. *               unsigned volume         playing volume (0-64)
  822. *
  823. * Returns:      MIDAS error code
  824. *
  825. \****************************************************************************/
  826.  
  827. int CALLING dsmSetVolume(unsigned channel, unsigned volume)
  828. {
  829.     /* Check that the channel number is legal and channels are open: */
  830.     if ( channel >= dsmChOpen )
  831.     {
  832.         ERROR(errInvalidChanNumber, ID_dsmSetVolume);
  833.         return errInvalidChanNumber;
  834.     }
  835.  
  836.     /* Set the volume: */
  837.     dsmChannels[channel].volume = volume;
  838.  
  839.     return OK;
  840. }
  841.  
  842.  
  843.  
  844.  
  845. /****************************************************************************\
  846. *
  847. * Function:     int dsmGetVolume(unsigned channel, unsigned *volume)
  848. *
  849. * Description:  Reads the playing volume
  850. *
  851. * Input:        unsigned channel        channel number
  852. *               unsigned *volume        pointer to volume
  853. *
  854. * Returns:      MIDAS error code. Playing volume is written to *volume.
  855. *
  856. \****************************************************************************/
  857.  
  858. int CALLING dsmGetVolume(unsigned channel, unsigned *volume)
  859. {
  860.     /* Check that the channel number is legal and channels are open: */
  861.     if ( channel >= dsmChOpen )
  862.     {
  863.         ERROR(errInvalidChanNumber, ID_dsmGetVolume);
  864.         return errInvalidChanNumber;
  865.     }
  866.  
  867.     /* Get the volume: */
  868.     *volume = dsmChannels[channel].volume;
  869.  
  870.     return OK;
  871. }
  872.  
  873.  
  874.  
  875.  
  876. /****************************************************************************\
  877. *
  878. * Function:     int dsmSetSample(unsigned channel, unsigned smpHandle)
  879. *
  880. * Description:  Sets the sample number on a channel
  881. *
  882. * Input:        unsigned channel        channel number
  883. *               unsigned smpHandle      sample handle returned by
  884. *                                       dsmAddSample()
  885. *
  886. * Returns:      MIDAS error code
  887. *
  888. \****************************************************************************/
  889.  
  890. int CALLING dsmSetSample(unsigned channel, unsigned smpHandle)
  891. {
  892.     dsmChannel  *chan;
  893.     dsmSample   *sample;
  894.     int         error;
  895.  
  896.     /* Check that the channel number is legal and channels are open: */
  897.     if ( channel >= dsmChOpen )
  898.     {
  899.         ERROR(errInvalidChanNumber, ID_dsmSetSample);
  900.         return errInvalidChanNumber;
  901.     }
  902.  
  903.     /* Check that the sample handle is valid and the sample is in use: */
  904.     if ( (smpHandle > MAXSAMPLES) || (dsmSamples[smpHandle-1].inUse == 0) )
  905.     {
  906.         ERROR(errInvalidSampleHandle, ID_dsmSetSample);
  907.         return errInvalidSampleHandle;
  908.     }
  909.  
  910.     chan = &dsmChannels[channel];
  911.     sample = &dsmSamples[smpHandle-1];
  912.  
  913.     /* Set new sample number to channel: */
  914.     chan->sampleHandle = smpHandle;
  915.  
  916.     /* Sample has been changed: */
  917.     chan->sampleChanged = 1;
  918.  
  919.     /* If the new sample has one Amiga-compatible loop and playing has ended
  920.        (not released or stopped), set the new sample and start playing from
  921.        loop start: */
  922.     if ( (sample->loopMode == sdLoopAmiga) && (chan->status == dsmChanEnd) )
  923.     {
  924.         /* Set sample and start playing: */
  925.         chan->status = dsmChanPlaying;
  926.         if ( (error = dsmSetPosition(channel, sample->loop1Start)) != OK )
  927.             PASSERROR(ID_dsmSetSample)
  928.     }
  929.  
  930.     return OK;
  931. }
  932.  
  933.  
  934.  
  935.  
  936. /****************************************************************************\
  937. *
  938. * Function:     int dsmGetSample(unsigned channel, unsigned *smpHandle)
  939. *
  940. * Description:  Reads current sample handle
  941. *
  942. * Input:        unsigned channel        channel number
  943. *               unsigned *smpHandle     pointer to sample handle
  944. *
  945. * Returns:      MIDAS error code. Sample handle is written to *smpHandle;
  946. *
  947. \****************************************************************************/
  948.  
  949. int CALLING dsmGetSample(unsigned channel, unsigned *smpHandle)
  950. {
  951.     /* Check that the channel number is legal and channels are open: */
  952.     if ( channel >= dsmChOpen )
  953.     {
  954.         ERROR(errInvalidChanNumber, ID_dsmGetSample);
  955.         return errInvalidChanNumber;
  956.     }
  957.  
  958.     /* Write sample handle to *smpHandle: */
  959.     *smpHandle = dsmChannels[channel].sampleHandle;
  960.  
  961.     return OK;
  962. }
  963.  
  964.  
  965.  
  966.  
  967. /****************************************************************************\
  968. *
  969. * Function:     int dsmChangeSample(unsigned channel)
  970. *
  971. * Description:  Changes the sample used in a channel to the one specified
  972. *               by the channel's sample handle. Used only internally by
  973. *               other DSM functions, does no error checking.
  974. *
  975. * Input:        unsigned channel        channel number
  976. *
  977. * Returns:      MIDAS error code (does not fail)
  978. *
  979. \****************************************************************************/
  980.  
  981. int CALLING dsmChangeSample(unsigned channel)
  982. {
  983.     dsmChannel  *chan = &dsmChannels[channel];
  984.     dsmSample   *sample = &dsmSamples[chan->sampleHandle-1];
  985.  
  986.     /* Start using the sample specified by chan->sampleHandle: */
  987.  
  988.     chan->sample = sample->sample;
  989.     chan->sampleType = sample->sampleType;
  990.     chan->samplePos = sample->samplePos;
  991.     chan->sampleLength = sample->sampleLength;
  992.     chan->loopMode = sample->loopMode;
  993.     chan->loop1Start = sample->loop1Start;
  994.     chan->loop1End = sample->loop1End;
  995.     chan->loop1Type = sample->loop1Type;
  996.     chan->loop2Start = sample->loop2Start;
  997.     chan->loop2End = sample->loop2End;
  998.     chan->loop2Type = sample->loop2Type;
  999.     chan->sampleChanged = 0;
  1000.  
  1001.     return OK;
  1002. }
  1003.  
  1004.  
  1005.  
  1006.  
  1007. /****************************************************************************\
  1008. *
  1009. * Function:     int dsmSetPosition(unsigned channel, unsigned position)
  1010. *
  1011. * Description:  Sets the playing position from the beginning of the sample
  1012. *
  1013. * Input:        unsigned channel        channel number
  1014. *               unsigned position       new playing position
  1015. *
  1016. * Returns:      MIDAS error code
  1017. *
  1018. \****************************************************************************/
  1019.  
  1020. int CALLING dsmSetPosition(unsigned channel, unsigned position)
  1021. {
  1022.     dsmChannel  *chan;
  1023.     int         error;
  1024.  
  1025.     /* Check that the channel number is legal and channels are open: */
  1026.     if ( channel >= dsmChOpen )
  1027.     {
  1028.         ERROR(errInvalidChanNumber, ID_dsmSetPosition);
  1029.         return errInvalidChanNumber;
  1030.     }
  1031.  
  1032.     chan = &dsmChannels[channel];
  1033.  
  1034.     /* Convert position from bytes to samples: */
  1035.     position = position >> dsmSampleShift(chan->sampleType);
  1036.  
  1037.     /* Check if sample has been changed, and if so, set the values to the
  1038.        channel structure: */
  1039.     if ( chan->sampleChanged )
  1040.     {
  1041.         if ( (error = dsmChangeSample(channel)) != OK )
  1042.             PASSERROR(ID_dsmSetPosition)
  1043.  
  1044.         /* If channel status is released and the new channel does not have
  1045.            two loops, end the sample: */
  1046.         if ( (chan->loopMode != sdLoop1Rel) && (chan->loopMode != sdLoop2) &&
  1047.             (chan->status == dsmChanReleased) )
  1048.         {
  1049.             chan->status = dsmChanEnd;
  1050.             return OK;
  1051.         }
  1052.     }
  1053.  
  1054.     /* Check that sample and playing rate have been set on the channel: */
  1055.     if ( (chan->sampleHandle != 0) && (chan->rate != 0) )
  1056.     {
  1057.         switch ( chan->status )
  1058.         {
  1059.             case dsmChanEnd:
  1060.             case dsmChanPlaying:
  1061.                 /* Either playing sample before releasing or playing has
  1062.                    ended - check the first loop type: */
  1063.                 chan->loopNum = 1;
  1064.                 switch ( chan->loop1Type )
  1065.                 {
  1066.                     case loopNone:
  1067.                         /* No looping - if position is below sample end, set
  1068.                            it and start playing there: */
  1069.                         if ( position < chan->sampleLength )
  1070.                         {
  1071.                             chan->playPos = position;
  1072.                             chan->playPosLow = 0;
  1073.                             chan->status = dsmChanPlaying;
  1074.                             chan->direction = dsmPlayForward;
  1075.                         }
  1076.                         else
  1077.                             chan->status = dsmChanEnd;
  1078.                         break;
  1079.  
  1080.                     case loopUnidir:
  1081.                         /* Unidirectional looping - if position is below
  1082.                            loop end, set it, otherwise set loop start as the
  1083.                            new position. Start playing in any case: */
  1084.                         if ( position < chan->loop1End )
  1085.                             chan->playPos = position;
  1086.                         else
  1087.                             chan->playPos = chan->loop1Start;
  1088.                         chan->playPosLow = 0;
  1089.                         chan->status = dsmChanPlaying;
  1090.                         chan->direction = dsmPlayForward;
  1091.                         break;
  1092.  
  1093.                     case loopBidir:
  1094.                         /* Bidirectional looping - if position is below loop
  1095.                            end, set it and start playing forward, otherwise
  1096.                            set loop end as the new position and start playing
  1097.                            backwards: */
  1098.                         if ( position < chan->loop1End )
  1099.                         {
  1100.                             chan->playPos = position;
  1101.                             chan->direction = dsmPlayForward;
  1102.                         }
  1103.                         else
  1104.                         {
  1105.                             chan->playPos = chan->loop1End;
  1106.                             chan->direction = dsmPlayBackwards;
  1107.                         }
  1108.                         chan->playPosLow = 0;
  1109.                         chan->status = dsmChanPlaying;
  1110.                 }
  1111.                 break;
  1112.  
  1113.             case dsmChanReleased:
  1114.                 /* Playing after sample has been released - check second loop
  1115.                    type: */
  1116.                 chan->loopNum = 2;
  1117.                 switch ( chan->loop2Type )
  1118.                 {
  1119.                     case loopNone:
  1120.                         /* No looping - if position is below sample end, set
  1121.                            it and start playing there: */
  1122.                         if ( position < chan->sampleLength )
  1123.                         {
  1124.                             chan->playPos = position;
  1125.                             chan->playPosLow = 0;
  1126.                             chan->status = dsmChanPlaying;
  1127.                             chan->direction = dsmPlayForward;
  1128.                         }
  1129.                         else
  1130.                             chan->status = dsmChanEnd;
  1131.                         break;
  1132.  
  1133.                     case loopUnidir:
  1134.                         /* Unidirectional looping - if position is below
  1135.                            loop end, set it, otherwise set loop start as the
  1136.                            new position. Start playing in any case: */
  1137.                         if ( position < chan->loop2End )
  1138.                             chan->playPos = position;
  1139.                         else
  1140.                             chan->playPos = chan->loop2Start;
  1141.                         chan->playPosLow = 0;
  1142.                         chan->status = dsmChanPlaying;
  1143.                         chan->direction = dsmPlayForward;
  1144.                         break;
  1145.  
  1146.                     case loopBidir:
  1147.                         /* Bidirectional looping - if position is below loop
  1148.                            end, set it and start playing forward, otherwise
  1149.                            set loop end as the new position and start playing
  1150.                            backwards: */
  1151.                         if ( position < chan->loop2End )
  1152.                         {
  1153.                             chan->playPos = position;
  1154.                             chan->direction = dsmPlayForward;
  1155.                         }
  1156.                         else
  1157.                         {
  1158.                             chan->playPos = chan->loop2End;
  1159.                             chan->direction = dsmPlayBackwards;
  1160.                         }
  1161.                         chan->playPosLow = 0;
  1162.                         chan->status = dsmChanPlaying;
  1163.                 }
  1164.                 break;
  1165.  
  1166.             case dsmChanStopped:
  1167.             default:
  1168.                 /* If sound has been stopped do nothing: */
  1169.                 break;
  1170.         }
  1171.     }
  1172.  
  1173.     return OK;
  1174. }
  1175.  
  1176.  
  1177.  
  1178.  
  1179. /****************************************************************************\
  1180. *
  1181. * Function:     int dsmGetPosition(unsigned channel, unsigned *position)
  1182. *
  1183. * Description:  Reads the current playing position
  1184. *
  1185. * Input:        unsigned channel        channel number
  1186. *               unsigned *position      pointer to playing position
  1187. *
  1188. * Returns:      MIDAS error code. Playing position is written to *position.
  1189. *
  1190. \****************************************************************************/
  1191.  
  1192. int CALLING dsmGetPosition(unsigned channel, unsigned *position)
  1193. {
  1194.     /* Check that the channel number is legal and channels are open: */
  1195.     if ( channel >= dsmChOpen )
  1196.     {
  1197.         ERROR(errInvalidChanNumber, ID_dsmGetPosition);
  1198.         return errInvalidChanNumber;
  1199.     }
  1200.  
  1201.     /* Write position to *position and convert to bytes: */
  1202.     *position = dsmChannels[channel].playPos << dsmSampleShift(
  1203.         dsmChannels[channel].sampleType);;
  1204.  
  1205.     return OK;
  1206. }
  1207.  
  1208.  
  1209.  
  1210.  
  1211. /****************************************************************************\
  1212. *
  1213. * Function:     int dsmGetDirection(unsigned channel, int *direction)
  1214. *
  1215. * Description:  Reads current playing direction
  1216. *
  1217. * Input:        unsigned channel        channel number
  1218. *               int *direction          pointer to playing direction. 1 is
  1219. *                                       forward, -1 backwards
  1220. *
  1221. * Returns:      MIDAS error code. Playing direction is written to *direction.
  1222. *
  1223. \****************************************************************************/
  1224.  
  1225. int CALLING dsmGetDirection(unsigned channel, int *direction)
  1226. {
  1227.     /* Check that the channel number is legal and channels are open: */
  1228.     if ( channel >= dsmChOpen )
  1229.     {
  1230.         ERROR(errInvalidChanNumber, ID_dsmGetDirection);
  1231.         return errInvalidChanNumber;
  1232.     }
  1233.  
  1234.     /* Write position to *position: */
  1235.     *direction = dsmChannels[channel].direction;
  1236.  
  1237.     return OK;
  1238. }
  1239.  
  1240.  
  1241.  
  1242.  
  1243. /****************************************************************************\
  1244. *
  1245. * Function:     int dsmSetPanning(unsigned channel, int panning)
  1246. *
  1247. * Description:  Sets the panning position of a channel
  1248. *
  1249. * Input:        unsigned channel        channel number
  1250. *               int panning             panning position (see enum sdPanning)
  1251. *
  1252. * Returns:      MIDAS error code
  1253. *
  1254. \****************************************************************************/
  1255.  
  1256. int CALLING dsmSetPanning(unsigned channel, int panning)
  1257. {
  1258.     /* Check that the channel number is legal and channels are open: */
  1259.     if ( channel >= dsmChOpen )
  1260.     {
  1261.         ERROR(errInvalidChanNumber, ID_dsmSetPanning);
  1262.         return errInvalidChanNumber;
  1263.     }
  1264.  
  1265.     /* Set panning position to channel: */
  1266.     dsmChannels[channel].panning = panning;
  1267.  
  1268.     return OK;
  1269. }
  1270.  
  1271.  
  1272.  
  1273.  
  1274. /****************************************************************************\
  1275. *
  1276. * Function:     int dsmGetPanning(unsigned channel, int *panning)
  1277. *
  1278. * Description:  Reads the panning position of a channel
  1279. *
  1280. * Input:        unsigned channel        channel number
  1281. *               int *panning            pointer to panning position
  1282. *
  1283. * Returns:      MIDAS error code. Panning position is written to *panning.
  1284. *
  1285. \****************************************************************************/
  1286.  
  1287. int CALLING dsmGetPanning(unsigned channel, int *panning)
  1288. {
  1289.     /* Check that the channel number is legal and channels are open: */
  1290.     if ( channel >= dsmChOpen )
  1291.     {
  1292.         ERROR(errInvalidChanNumber, ID_dsmGetPanning);
  1293.         return errInvalidChanNumber;
  1294.     }
  1295.  
  1296.     /* Write panning position to *panning: */
  1297.     *panning = dsmChannels[channel].panning;
  1298.  
  1299.     return OK;
  1300. }
  1301.  
  1302.  
  1303.  
  1304.  
  1305. /****************************************************************************\
  1306. *
  1307. * Function:     int dsmMuteChannel(unsigned channel, int mute)
  1308. *
  1309. * Description:  Mutes/un-mutes a channel
  1310. *
  1311. * Input:        unsigned channel        channel number
  1312. *               int mute                muting status - 1 = mute, 0 = un-mute
  1313. *
  1314. * Returns:      MIDAS error code
  1315. *
  1316. \****************************************************************************/
  1317.  
  1318. int CALLING dsmMuteChannel(unsigned channel, int mute)
  1319. {
  1320.     /* Check that the channel number is legal and channels are open: */
  1321.     if ( channel >= dsmChOpen )
  1322.     {
  1323.         ERROR(errInvalidChanNumber, ID_dsmMuteChannel);
  1324.         return errInvalidChanNumber;
  1325.     }
  1326.  
  1327.     /* Set muting status: */
  1328.     dsmChannels[channel].muted = mute;
  1329.  
  1330.     return OK;
  1331. }
  1332.  
  1333.  
  1334.  
  1335.  
  1336. /****************************************************************************\
  1337. *
  1338. * Function:     int dsmAddSample(sdSample *sample, int copySample,
  1339. *                   unsigned *smpHandle);
  1340. *
  1341. * Description:  Adds a new sample to the DSM sample list and prepares it for
  1342. *               DSM use
  1343. *
  1344. * Input:        sdSample *sample        pointer to sample information
  1345. *                                           structure
  1346. *               int copySample          copy sample data to a new place in
  1347. *                                       memory? 1 = yes, 0 = no
  1348. *               unsigned *smpHandle     pointer to sample handle
  1349. *
  1350. * Returns:      MIDAS error code. Sample handle for the new sample is written
  1351. *               to *smpHandle
  1352. *
  1353. * Notes:        If copySample = 1, sample data must not be in EMS memory.
  1354. *               If copySample = 0 and sample is 16-bit, the sample data WILL
  1355. *               be modified by this function.
  1356. *
  1357. \****************************************************************************/
  1358.  
  1359. int CALLING dsmAddSample(sdSample *sample, int copySample, unsigned
  1360.     *smpHandle)
  1361. {
  1362.     int         i, handle, error;
  1363.     static void *copyDest;
  1364.     dsmSample   *dsmSmp;
  1365.     unsigned    destLength;             /* destination sample length */
  1366.     int         smpShift;
  1367.  
  1368.     /* Find first unused sample handle: */
  1369.     handle = 0;
  1370.     for ( i = 0; i < MAXSAMPLES; i++ )
  1371.     {
  1372.         if ( dsmSamples[i].inUse == 0 )
  1373.         {
  1374.             handle = i+1;
  1375.             break;
  1376.         }
  1377.     }
  1378.  
  1379.     /* Check if an empty handle was found. If not, return an error: */
  1380.     if ( handle == 0 )
  1381.     {
  1382.         ERROR(errNoSampleHandles, ID_dsmAddSample);
  1383.         return errNoSampleHandles;
  1384.     }
  1385.  
  1386.     /* Point dsmSmp to new sample: */
  1387.     dsmSmp = &dsmSamples[handle-1];
  1388.  
  1389.     /* Mark sample used: */
  1390.     dsmSmp->inUse = 1;
  1391.  
  1392.     smpShift = dsmSampleShift(sample->sampleType);
  1393.  
  1394.     /* Copy sample information: */
  1395.     dsmSmp->sampleType = sample->sampleType;
  1396.     dsmSmp->sampleLength = sample->sampleLength >> smpShift;
  1397.     dsmSmp->loopMode = sample->loopMode;
  1398.     dsmSmp->loop1Start = sample->loop1Start >> smpShift;
  1399.     dsmSmp->loop1End = sample->loop1End >> smpShift;
  1400.     dsmSmp->loop1Type = sample->loop1Type;
  1401.     dsmSmp->loop2Start = sample->loop2Start >> smpShift;
  1402.     dsmSmp->loop2End = sample->loop2End >> smpShift;
  1403.     dsmSmp->loop2Type = sample->loop2Type;
  1404.  
  1405.     if ( (sample->sampleType == smpNone) || (sample->sampleLength == 0) ||
  1406.         (sample->sample == NULL) || (sample->samplePos == sdSmpNone) )
  1407.     {
  1408.         /* There is no sample - set up DSM sample structure accordingly: */
  1409.         dsmSmp->sampleType = smpNone;
  1410.         dsmSmp->sampleLength = 0;
  1411.         dsmSmp->sample = NULL;
  1412.         dsmSmp->copied = 0;
  1413.         dsmSmp->samplePos = sdSmpNone;
  1414.     }
  1415.     else
  1416.     {
  1417.         if ( copySample )
  1418.         {
  1419.             /* Sample data should be copied elsewhere in memory */
  1420.             destLength = sample->sampleLength;
  1421.  
  1422.             /* Allocate memory for sample: */
  1423.             if ( (error = memAlloc(destLength, (void**) &dsmSmp->sample))
  1424.                 != OK )
  1425.                 PASSERROR(ID_dsmAddSample)
  1426.  
  1427.             copyDest = dsmSmp->sample;
  1428.  
  1429.             /* Sample is in conventional memory: */
  1430.             dsmSmp->samplePos = sdSmpConv;
  1431.  
  1432.             /* Copy sample data: */
  1433.             mMemCopy(copyDest, sample->sample, destLength);
  1434.  
  1435.             /* Sample is copied and should be deallocated when removed: */
  1436.             dsmSmp->copied = 1;
  1437.         }
  1438.         else
  1439.         {
  1440.             /* There is sample data, but it should not be copied - copy sample
  1441.                pointer and position: */
  1442.             dsmSmp->sample = sample->sample;
  1443.             dsmSmp->samplePos = sample->samplePos;
  1444.             dsmSmp->copied = 0;
  1445.         }
  1446.     }
  1447.  
  1448.     /* Write sample handle to *smpHandle: */
  1449.     *smpHandle = handle;
  1450.  
  1451.     return OK;
  1452. }
  1453.  
  1454.  
  1455.  
  1456.  
  1457. /****************************************************************************\
  1458. *
  1459. * Function:     int dsmRemoveSample(unsigned smpHandle)
  1460. *
  1461. * Description:  Removes a sample from the sample list and deallocates it if
  1462. *               necessary.
  1463. *
  1464. * Input:        unsigned smpHandle      sample handle returned by
  1465. *                                       dsmAddSample()
  1466. *
  1467. * Returns:      MIDAS error code
  1468. *
  1469. \****************************************************************************/
  1470.  
  1471. int CALLING dsmRemoveSample(unsigned smpHandle)
  1472. {
  1473.     dsmSample   *sample;
  1474.     int         error;
  1475.  
  1476.     /* Check that the sample handle is valid and the sample is in use: */
  1477.     if ( (smpHandle > MAXSAMPLES) || (dsmSamples[smpHandle-1].inUse == 0) )
  1478.     {
  1479.         ERROR(errInvalidSampleHandle, ID_dsmRemoveSample);
  1480.         return errInvalidSampleHandle;
  1481.     }
  1482.  
  1483.     sample = &dsmSamples[smpHandle-1];
  1484.  
  1485.     /* Mark sample unused: */
  1486.     sample->inUse = 0;
  1487.  
  1488.     /* Check if sample data should be deallocated: */
  1489.     if ( sample->copied )
  1490.     {
  1491.         if ( (error = memFree(sample->sample)) != OK )
  1492.             PASSERROR(ID_dsmRemoveSample)
  1493.     }
  1494.  
  1495.     return OK;
  1496. }
  1497.  
  1498.  
  1499.  
  1500.  
  1501. /****************************************************************************\
  1502. *
  1503. * Function:     int dsmMixData(unsigned numElems)
  1504. *
  1505. * Description:  Mixes data to dsmMixBuffer.
  1506. *
  1507. * Input:        unsigned numElems       number of buffer elements to be mixed.
  1508. *                                       In mono modes an "element" is an
  1509. *                                       unsigned integer, and in stereo
  1510. *                                       two.
  1511. *
  1512. * Returns:      MIDAS error code. Mixed data is written to *dsmMixBuffer.
  1513. *
  1514. \****************************************************************************/
  1515.  
  1516. int CALLING dsmMixData(unsigned numElems)
  1517. {
  1518.     int         error;
  1519.     unsigned    ch;
  1520.     unsigned    volume;
  1521.     dsmChannel  *chan;
  1522.     void        *mixRoutine;
  1523.  
  1524.     /* If playing is paused, no channels are open or data on channels may not
  1525.        be used, just clear the buffer and exit: */
  1526.     if ( dsmPaused || (dsmChOpen == 0) || (!dsmChPlay) )
  1527.     {
  1528.         if ( (error = dsmClearBuffer(numElems)) != OK )
  1529.             PASSERROR(ID_dsmMixData)
  1530.         return OK;
  1531.     }
  1532.  
  1533.     for ( ch = 0; ch < dsmChOpen; ch++ )
  1534.     {
  1535.         chan = &dsmChannels[ch];
  1536.  
  1537.         /* Point mixRoutine to correct low-level mixing routine: */
  1538.         mixRoutine = mixingRoutines[dsmMode][chan->sampleType];
  1539.  
  1540.         /* If current channel is muted or DSM is muted, set channel volume to
  1541.            zero, otherwise calculate it: */
  1542.         if ( chan->muted || dsmMuted )
  1543.             volume = 0;
  1544.         else
  1545.             volume = (chan->volume * dsmMasterVolume) / 64;
  1546.  
  1547.         /* Mix data for this channel: */
  1548.         if ( (error = dsmMix(ch, mixRoutine, volume, numElems)) != OK )
  1549.             PASSERROR(ID_dsmMixData)
  1550.     }
  1551.  
  1552.     return OK;
  1553. }
  1554.  
  1555.  
  1556.  
  1557. #ifdef SUPPORTSTREAMS
  1558.  
  1559.  
  1560. /****************************************************************************\
  1561. *
  1562. * Function:     int dsmStartStream(unsigned channel, uchar *buffer,
  1563. *                   unsigned bufferLength, int sampleType);
  1564. *
  1565. * Description:  Starts playing a digital audio stream on a channel
  1566. *
  1567. * Input:        unsigned channel        channel number
  1568. *               uchar *buffer           pointer to stream buffer
  1569. *               unsigned bufferLength   buffer length in bytes
  1570. *               int sampleType          stream sample type
  1571. *               ulong rate              stream playing rate (in Hz)
  1572. *
  1573. * Returns:      MIDAS error code
  1574. *
  1575. \****************************************************************************/
  1576.  
  1577. int CALLING dsmStartStream(unsigned channel, uchar *buffer, unsigned
  1578.     bufferLength, int sampleType, ulong rate)
  1579. {
  1580.     dsmChannel  *chan;
  1581.  
  1582.     /* Check that the channel number is legal and channels are open: */
  1583.     if ( channel >= dsmChOpen )
  1584.     {
  1585.         ERROR(errInvalidChanNumber, ID_dsmStartStream);
  1586.         return errInvalidChanNumber;
  1587.     }
  1588.  
  1589.     chan = &dsmChannels[channel];
  1590.  
  1591.     /* Set up channel for playing the stream: */
  1592.     chan->sample = buffer;
  1593.     chan->sampleType = sampleType;
  1594.     chan->samplePos = sdSmpConv;
  1595.     chan->sampleLength = bufferLength >> dsmSampleShift(sampleType);
  1596.     chan->loopMode = sdLoop1;
  1597.     chan->loop1Start = 0;
  1598.     chan->loop1End = bufferLength >> dsmSampleShift(sampleType);
  1599.     chan->loop1Type = loopUnidir;
  1600.     chan->loop2Start = chan->loop2End = 0;
  1601.     chan->loop2Type = sdLoopNone;
  1602.     chan->playPos = chan->playPosLow = 0;
  1603.     chan->rate = rate;
  1604.     chan->direction = dsmPlayForward;
  1605.     chan->sampleHandle = DSM_SMP_STREAM;        /* magic */
  1606.     chan->sampleChanged = 0;
  1607.     chan->panning = panMiddle;
  1608.     chan->volume = 64;
  1609.     chan->muted = 0;
  1610.     chan->loopNum = 1;
  1611.     chan->status = dsmChanPlaying;
  1612.     chan->streamWritePos = 0;
  1613.  
  1614.     return OK;
  1615. }
  1616.  
  1617.  
  1618.  
  1619.  
  1620. /****************************************************************************\
  1621. *
  1622. * Function:     int dsmStopStream(unsigned channel);
  1623. *
  1624. * Description:  Stops playing digital audio stream on a channel
  1625. *
  1626. * Input:        unsigned channel        channel number
  1627. *
  1628. * Returns:      MIDAS error code
  1629. *
  1630. \****************************************************************************/
  1631.  
  1632. int CALLING dsmStopStream(unsigned channel)
  1633. {
  1634.     /* Check that the channel number is legal and channels are open: */
  1635.     if ( channel >= dsmChOpen )
  1636.     {
  1637.         ERROR(errInvalidChanNumber, ID_dsmStopSound);
  1638.         return errInvalidChanNumber;
  1639.     }
  1640.  
  1641.     /* Stop sound: */
  1642.     dsmChannels[channel].status = dsmChanStopped;
  1643.  
  1644.     return OK;
  1645. }
  1646.  
  1647.  
  1648.  
  1649.  
  1650. /****************************************************************************\
  1651. *
  1652. * Function:     int dsmSetLoopCallback(unsigned channel,
  1653. *                   void (CALLING *callback)(unsigned channel));
  1654. *
  1655. * Description:  Sets sample looping callback to a channel
  1656. *
  1657. * Input:        unsigned channel        channel number
  1658. *               [..] *callback          pointer to callback function, NULL to
  1659. *                                       disable callback
  1660. *
  1661. * Returns:      MIDAS error code
  1662. *
  1663. \****************************************************************************/
  1664.  
  1665. int CALLING dsmSetLoopCallback(unsigned channel,
  1666.     void (CALLING *callback)(unsigned channel))
  1667. {
  1668.     /* Check that the channel number is legal and channels are open: */
  1669.     if ( channel >= dsmChOpen )
  1670.     {
  1671.         ERROR(errInvalidChanNumber, ID_dsmStopSound);
  1672.         return errInvalidChanNumber;
  1673.     }
  1674.  
  1675.     /* Set callback: */
  1676.     dsmChannels[channel].LoopCallback = callback;
  1677.  
  1678.     return OK;
  1679. }
  1680.  
  1681.  
  1682.  
  1683.  
  1684. /****************************************************************************\
  1685. *
  1686. * Function:     int dsmSetStreamWritePosition(unsigned channel,
  1687. *                   unsigned position)
  1688. *
  1689. * Description:  Sets the stream write position on a channel
  1690. *
  1691. * Input:        unsigned channel        channel number
  1692. *               unsigned position       new stream write position
  1693. *
  1694. * Returns:      MIDAS error code
  1695. *
  1696. \****************************************************************************/
  1697.  
  1698. int CALLING dsmSetStreamWritePosition(unsigned channel, unsigned position)
  1699. {
  1700.     dsmChannel  *chan;
  1701.  
  1702.     /* Check that the channel number is legal and channels are open: */
  1703.     if ( channel >= dsmChOpen )
  1704.     {
  1705.         ERROR(errInvalidChanNumber, ID_dsmSetStreamWritePosition);
  1706.         return errInvalidChanNumber;
  1707.     }
  1708.  
  1709.     chan = &dsmChannels[channel];
  1710.  
  1711.     chan->streamWritePos = position >> dsmSampleShift(chan->sampleType);
  1712.  
  1713.     return OK;
  1714. }
  1715.  
  1716.  
  1717.  
  1718.  
  1719. #endif /* #ifdef SUPPORTSTREAMS */
  1720.  
  1721.  
  1722.  
  1723.  
  1724. /*
  1725.  * $Log: dsm.c,v $
  1726.  * Revision 1.11  1997/01/16 18:41:59  pekangas
  1727.  * Changed copyright messages to Housemarque
  1728.  *
  1729.  * Revision 1.10  1997/01/16 18:19:10  pekangas
  1730.  * Added support for setting the stream write position.
  1731.  * Stream data is no longer played past the write position
  1732.  *
  1733.  * Revision 1.9  1996/10/09 15:54:22  pekangas
  1734.  * Fixed dsmReleaseSound() to work as specified
  1735.  *
  1736.  * Revision 1.8  1996/07/13 19:44:22  pekangas
  1737.  * Eliminated Visual C warnings
  1738.  *
  1739.  * Revision 1.7  1996/07/13 18:40:48  pekangas
  1740.  * Fixed to compile with Visual C
  1741.  *
  1742.  * Revision 1.6  1996/06/26 19:14:55  pekangas
  1743.  * Added sample loop callbacks
  1744.  *
  1745.  * Revision 1.5  1996/05/30 21:10:27  pekangas
  1746.  * Fixed a small bug in looping other samples than 8-bit mono
  1747.  *
  1748.  * Revision 1.4  1996/05/28 20:31:11  pekangas
  1749.  * Added support for 8-bit stereo and 16-bit mono and stereo samples
  1750.  *
  1751.  * Revision 1.3  1996/05/26 20:55:39  pekangas
  1752.  * Implemented digital audio stream support
  1753.  *
  1754.  * Revision 1.2  1996/05/24 16:19:39  jpaana
  1755.  * Misc fixes for Linux
  1756.  *
  1757.  * Revision 1.1  1996/05/22 20:49:33  pekangas
  1758.  * Initial revision
  1759.  *
  1760. */